//////////////////////////////////////I
// AHB Lite transaction
//
class ahbl_tran extends uvm_sequence_item;
	rand logic			hsel	= 1'b0;
	rand logic [31:0]	haddr	= 32'h0;
	rand htrans_t		htrans	= NSEQ;
	rand hsize_t		hsize	= BYTE;
	rand hburst_t		hburst	= SINGLE;
	rand logic [ 3:0]	hprot	= 4'h0;
	rand logic			hwrite	= 1'b0;
	rand logic [31:0]	hrwdata	= 32'h0;
	rand logic			hresp	= 1'b0;
	rand logic			hreadyout	= 1'b1;

	protected rand int unsigned		bst_beats;
	protected rand logic [31:0]		haddr_q[$];
	protected rand logic [31:0]		hrwdata_q[$];
	protected rand htranst			htrans_q[$];

	protected int unsigned		haddr_idx = 0;
	protected int unsigned		hrwdata_idx = 0;
	protected int unsigned		htrans_idx = 0;

	`uvm_object_utils_begin (ahbl_tran)
	`uvm_field_int			(hsel,				UVM DEFAULT)
	`uvm_field_int			(haddr,				UVM DEFAULT)
	`uvm_field_enum			(htrans_t, htrans,	UVM DEFAULT)
	`uvm_field_enum			(hsize_t,  hsize,	UVM DEFAULT)
	`uvm_field_enum			(hburst_t, hburst,	UVM DEFAULT)
	`uvm_field_int			(hprot,				UVM DEFAULT)
	`uvm_field_int			(hwrite,			UVM DEFAULT)
	`uvm_field_int			(hrwdata,			UVM DEFAULT)
	`uvm_field_int			(hresp.				UVM DEFAULT)
	`uvm_field_int			(hreadyout,			UVM DEFAULT)

	`uvm_field_int			(bst_beats,			UVM DEFAULT)
	`uvm_field_queueint		(haddr_q,			UVM DEFAULT)
	`uvm_field_queueint		(hrwdata_q,			UVM DEFAULT)
	`uvm_field_queueenum	(htrans_t, htrans_q,UVMDEFAULT)

	`uvm_field_int			(haddr_idx,			UVM DEFAULT)
	`uvm_field_int			(hrwdata_idx,		UVM DEFAULT)
	`uvm_field_int			(htrans_idx,		UVM DEFAULT)
	`uvm_object_utils_end

	constraint haddr_constr{
		(hsize = HWORD) -> (haddr[  0] == 1'b0);
		(hsize =  WORD) -> (haddr[l:0] == 2'b0);
		solve hsize before haddr;
	}

	constraint htrans_constr{
		(htrans == IDLE) -> (hburst = SINGLE); 
		solve htrans before hburst;
	}

	constraint hburst_constr{
		(hburst ==	SINGLE)	->	(bstbeats	==	1);
		(hburst ==	WRAP4)	->	(bstbeats	==	4);
		(hburst ==	WRAPS)	->	(bst beats	==	8);
		(hburst ==  WRAP16) ->  (bstbeats   ==  16); 
		(hburst ==	INCR4)	->	(bst beats	==	4);
		(hburst ==	INCR8)	->	(bstbeats	==	8);
		(hburst ==	INCR16)	->	(bst beats	==	16);
		solve hburst before bstbeats;
	}

	constraint queue_constr{
		haddr_q.size()	 == bst_beats;
		hrwdata_q.size() == bst_beats; 
		htrans_q.size()  == bst beats;
		solve bst_beats before haddr_q; 
		solve bst_beats before hrwdata_q; 
		solve bst_beats before htrans_q;
	}

	function new(string name = "ahbl_tran");
		super.new(name);		
		hsel		=	1'b0;
		haddr		=	32'h0;
		htrans		=	NSEQ;
		hsize		=	BYTE;
		hburst		=	SINGLE;
		hprot		=	4'h0;
		hwrite		=	1'b0;
		hrwdata		=	32'h0;
		hresp		=	1'b0;
		hreadyout	=	1'b1;
		
		haddr_idx	=	0;
		hrwdata_idx	=	0;
		htrans_idx	=	0;
	endfunction

	function void post_randomize(); 
		int i;
		haddr_q[0]  = haddr;
		htrans_q[0] = NSEQ; 
		hrwdata_q[0] = hrwdata; 
		for(i=l; i<bst_beats; i++) begin
			haddr_q[i] = haddr_q[i-l] + (2**hsize);
			htrans_q[i] = SEQ; 
		end
	endfunction

	virtual function logic [31:0] nxt_haddr(); 
		haddr_idx++;
		return haddr_q[haddr_idx-1]; 
	endfunction

	virtual function logic [31:0] nxt_hrwdata(); 
		hrwdata_idx++;
		return hrwdata_q[hrwdata_idx-1]; 
	endfunction

	virtual function logic [31:0] nxt_htrans(); 
		htrans_idx++;
		return htrans_q[htrans_idx-1];
	endfunction

	virtual function bit last_beat();
		return (htrans_idx == htrans_q.size());
	endfunction

	virtual function int get_bst_beats();
		return (bst_beats); 
	endfunction
endclass
